/*
 * @Descripttion: 
 * @version: 
 * @Author: yuxintao
 * @Date: 2022-04-29 14:53:43
 * @LastEditors: yuxintao
 * @LastEditTime: 2022-04-29 15:49:25
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

char *ethname = "ens33";
int fd;
char ef[ETH_FRAME_LEN];//以太网帧缓冲区
int flag[3];
char* app_data = NULL;
int app_len;
int n;

int main() {
    bzero(flag, sizeof(flag));
    fd = socket(AF_INET, SOCK_PACKET, htons(0x0003));
    if (fd == -1) {
        perror("socket");
        exit(1);
    }
    //设置网卡的ens33接口为混杂模式
    struct ifreq ifr;
    memcpy(ifr.ifr_ifrn.ifrn_name, ethname, strlen(ethname));
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
        close(fd);
        perror("ioctl 1");
        exit(1);
    }
    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
        close(fd);
        perror("ioctl 2");
        exit(1);
    }
    struct ethhdr* p_ethhdr = (struct ethhdr*)ef;
    while (1) {
        //直接从网卡的ens33获得一个数据帧
        if (flag[0] == 1 && flag[1] == 1 && flag[2] == 1) {
            break;
        }
        bzero(ef, ETH_FRAME_LEN);
        if ((n = recv(fd, ef, ETH_FRAME_LEN, 0)) <= 0) {
            perror("recv");
            exit(1);
        }
        printf("sourcce MAC: ");
        for (int i = 0; i < 6; ++i) {
            printf("%02x-", p_ethhdr->h_source[i]);
        }
        printf("dest MAX: ");
        for (int i = 0; i < 6; ++i) {
            printf("%02x-", p_ethhdr->h_dest[i]);
        }
        //协议类型，0x0800为IP协议，0x0806为ARP协议，0x8035为RARP协议
        printf("protocol: 0x%04x\n", htons(p_ethhdr->h_proto));

        if (p_ethhdr->h_proto = htons(0x800)) {
            struct iphdr* p_iphdr = (struct iphdr*)(ef + ETH_HLEN);
            struct sockaddr_in tmp;
            tmp.sin_addr.s_addr = p_iphdr->saddr;
            printf("src ip: %s ", inet_ntoa(tmp.sin_addr));
            tmp.sin_addr.s_addr = p_iphdr->daddr;
            printf("dest ip: %s\n", inet_ntoa(tmp.sin_addr));
            flag[0] = 1;
            if (p_iphdr->protocol == 17) {//UDP
                struct udphdr* p_udp = (struct udphdr*)((char*)p_iphdr + p_iphdr->ihl * 4);
                printf("udp src port: %d ", htons(p_udp->source));
                printf("udp dest prot: %d \n", htons(p_udp->dest));
                flag[1] = 1;
                app_data = (char*)p_udp + 8;
                app_len = n - 16 - p_iphdr->ihl * 4 - 8;
                printf("application data address: 0x%x, length: %d\n\n", (int)app_data, app_len);
            } else if (p_iphdr->protocol == 6) { //TCP
                struct tcphdr* p_tcp = (struct tcphdr*)((char*)p_iphdr + p_iphdr->ihl * 4);
                printf("tcp source port: %d ", p_tcp->source);
                printf("tcp dest port: %d\n", p_tcp->dest);
                flag[2] = 1;
                app_data = (char*)p_tcp + 20;
                app_len = n - 16 - p_iphdr->ihl * 4 - 20;
                printf("application data address: 0x%x, length: %d\n\n", (int)app_data, app_len);
            }
        }
    }
    return 0;
}